#include "video.h"
#include "error.h"

int VideoReader::Init(string filename) {
    _filename = filename;
    int ret = 0;
    av_register_all();

    // 从传入的第二个参数获得文件路径，这个函数会读取文件头信息，并把信息保存在 pFormatCtx 结构体当中。
    // 这个函数后面两个参数分别是： 指定文件格式、格式化选项，当我们设置为 NULL 或 0 时，libavformat 会自动完成这些工作。
    if(ret = avformat_open_input(&_pFormatCtx, _filename.c_str(), NULL, NULL), ret!=0) {
        fprintf(stderr, "Could not open file:%s  ret:%d\n",_filename.c_str(), ret);
        return MM_ERR_FILE_OPEN;
    }

    // 得到流信息
    if(ret = avformat_find_stream_info(_pFormatCtx, NULL), ret<0) {
        fprintf(stderr, "Could not find stream info ret:%d\n", ret);
        return MM_ERR_FIND_STREAM; // Couldn't find stream information
    }

    av_dump_format(_pFormatCtx, 0, _filename.c_str(), 0);

    for(int i=0; i< _pFormatCtx->nb_streams; i++) {
    if(_pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO && _videoStream <0) {
        _videoStream = i;
     }
    }

    if( _videoStream == -1) {
        fprintf(stderr, "Could not find stream\n");
        return MM_ERR_FIND_STREAM;
    }

    _pCodecCtx= _pFormatCtx->streams[_videoStream]->codec;
    return MM_OK;
}

VideoReader::~VideoReader() {
    if(_pCodecCtx != nullptr) {
        avcodec_close(_pCodecCtx);
        _pCodecCtx = nullptr;
    }
  
    if(_pFormatCtx != nullptr) {
        avformat_close_input(&_pFormatCtx);
        _pFormatCtx = nullptr;
    }
}

int VideoReader::GetPacket(uint8_t* pBuf, int* pSize) {
    AVPacket packet;
    int ret = av_read_frame(_pFormatCtx, &packet);
    if(ret >= 0) {
        if(packet.stream_index == _videoStream) {
            // 如果是视频就放置到音频队列 
            if(*pSize >= packet.size) {
                memcpy(pBuf,packet.data, packet.size);
                *pSize = packet.size;
            }else {
                av_free_packet(&packet);
                return MM_ERR_BUFFER_NOT_ENOUGH;
            } 
        } else {
            av_free_packet(&packet);
        }
        return MM_OK;
    }    
    fprintf(stderr, "read audio paket failed ret:%d\n", ret);
    return MM_ERR_READ_PAKCET;
}